package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.constant.MessageConstant;
import com.sky.dto.PageQuery;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.Book;
import com.sky.entity.User;
import com.sky.entity.UserActionLog;
import com.sky.exception.LoginFailedException;
import com.sky.mapper.UserMapper;
import com.sky.properties.WeChatProperties;
import com.sky.repository.BookRepository;
import com.sky.repository.UserActionLogRepository;
import com.sky.result.PageResult;
import com.sky.service.UserService;
import com.sky.utils.HttpClientUtil;
import com.sky.vo.UserActionLogVO;
import com.sky.vo.UserInfoVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    // 微信登录接口配置
    public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WeChatProperties weChatProperties;
    @Autowired
    private BookRepository bookRepository;
    @Autowired
    private UserActionLogRepository logRepository;

    /**
     * 微信登录
     * @param userDTO 用户登录DTO
     * @return 用户信息
     * @throws LoginFailedException 登录失败异常
     */
    public User wxLogin(UserLoginDTO userDTO) {
        Assert.notNull(userDTO, "UserLoginDTO cannot be null");
        Assert.hasText(userDTO.getCode(), "Code cannot be empty");

        String openId = getOpenId(userDTO.getCode());

        if (openId == null) {
            throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
        }

        User user = userMapper.getByOpenId(openId);
        if (user == null) {
            user = User.builder()
                    .openId(openId)
                    .avatar(userDTO.getAvatar())
                    .nickname(userDTO.getNickname())
                    .status(User.UN_BAN)
                    .createTime(new Date())
                    .build();
            userMapper.insert(user);
        }
        return user;
    }

    /**
     * 获取微信openId
     * @param code 微信code
     * @return openId
     */
    private String getOpenId(String code) {
        Map<String, String> params = new HashMap<>();
        params.put("appId", weChatProperties.getAppid());
        params.put("secret", weChatProperties.getSecret());
        params.put("js_code", code);
        params.put("grant_type", "authorization_code");

        String json = HttpClientUtil.doGet(WX_LOGIN, params);
        JSONObject jsonObject = JSON.parseObject(json);
        return jsonObject.getString("openid");
    }

    /**
     * 分页查询用户列表
     * @param pageQuery 分页查询参数
     * @return 分页结果
     */
    public PageResult pageQuery(PageQuery pageQuery) {
        Assert.notNull(pageQuery, "PageQuery cannot be null");

        Page<User> page = new Page<>(pageQuery.getPage(), pageQuery.getSize());
        userMapper.selectPage(page, null);
        return new PageResult(page.getTotal(), page.getRecords());
    }

    /**
     * 获取当前用户详情
     * @param id 用户ID
     * @return 用户信息VO
     */
    public UserInfoVO currentUser(Integer id) {
        Assert.notNull(id, "User id cannot be null");

        User user = userMapper.getById(id);
        UserInfoVO userInfoVO = new UserInfoVO();
        BeanUtils.copyProperties(user, userInfoVO);
        return userInfoVO;
    }

    /**
     * 获取用户行为日志
     * @param id 用户ID
     * @return 用户行为日志VO列表
     */
    public List<UserActionLogVO> logs(Integer id) {
        Assert.notNull(id, "User id cannot be null");

        // 按时间戳降序获取前50条日志
        List<UserActionLog> logs = logRepository.findTop50ByuIdOrderByTimestampDesc(id);
        return logs.stream()
                .map(this::convertToActionLogVO)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 将用户行为日志转换为VO对象
     * @param log 用户行为日志
     * @return 用户行为日志VO
     */
    private UserActionLogVO convertToActionLogVO(UserActionLog log) {
        if (log == null || log.getAction() == null) {
            return null;
        }

        Book book = bookRepository.findById(log.getBId()).orElse(null);
        if (book == null) {
            return null;
        }

        return switch (log.getAction()) {
            case "read" -> buildActionLogVO(log, book, "read", "阅读了《%s》");
            case "like" -> buildActionLogVO(log, book, "like", "点赞了《%s》");
            case "collect" -> buildActionLogVO(log, book, "collect", "收藏了《%s》");
            case "review" -> buildActionLogVO(log, book, "review", "评论了《%s》");
            case "note" -> buildActionLogVO(log, book, "note", "创建了《%s》的笔记");
            default -> null;
        };
    }

    /**
     * 构建用户行为日志VO
     * @param log 原始日志
     * @param book 相关书籍
     * @param type 日志类型
     * @param contentFormat 内容格式
     * @return 用户行为日志VO
     */
    private UserActionLogVO buildActionLogVO(UserActionLog log, Book book, String type, String contentFormat) {
        UserActionLogVO vo = new UserActionLogVO();
        BeanUtils.copyProperties(log, vo);
        vo.setType(type);
        vo.setContent(String.format(contentFormat, book.getTitle()));
        vo.setBook(book);
        return vo;
    }
}